5장. (part1) 변하지 않는 것은 없다
- 5장. (part1) 변하지 않는 것은 없다
- 1. 우리의 디자인을 시험해 봅시다.
- UML 컨닝 페이퍼
1. 우리의 디자인을 시험해 봅시다.
- 분석과 설계를 잘하면 재사용성과 확장성이 좋은 소프트웨어를 만들 수 있다.
1.1 릭의 기타 검색 도구에서 만돌린도 검색가능하도록 수정해보자.
- 릭의 기타 검색 프로그램의 클래스 다이어그램 완성본이다.

- 릭의 검색 도구로 만돌린도 검색할 수 있게 하세요.

1.2 추상 부모 클래스라는 것을 알고있나요?
추상클래스는 실제 구현 클래스를 위한 저장장소입니다.
추상클래스는 기능(behavior)을 정의하고, 그 기능을 서브클래스가 구현합니다..
- Instrument는 추상 클래스이다.
객체를 생성할 수 없다.
Mandolin이나 Guitar 같은 Instrument의 서브 클래스를 정의해야 ?나.
실제 구현 클래스들을 위해 존재하는 일반적인(generic)클래스 이다.
1.3 릭의 새 프로그램
*두개 이상의 클래스에서 공통된 행동(기능)을 발견할때마다, 그 행동을 하나의 클래스로 추상화하여 그 행동(기능)을 재사용하도록 하세요.

UML 컨닝 페이퍼
| JAVA 부르기 | UML 부르기 | UML 나타내기 |
|---|
| 관계(relationship) | 연관(association) |  |
| 상속(inheritance) | 일반화(generalization) |  |
| 집합(aggregation) | 집합(aggregation) |  |
1.4 릭의 새로운 검색도구를 코드로 작성하자.
| Instrument.java | Guitar.java / Mandolin.java |
|---|
{code} public abstract class Instrument { //=============================================================================================== // 객체생성 //
--- private String SerialNumber; private double price; private InstrumentSpec spec;;; //=============================================================================================== |
public Instrument (String serialNumber, double price, InstrumentSpec) {
//
---
this.serialNumber = serialNumber;
this.price = price;
this.spec = spec;
//
---
}
public InstrumentSpec getSpec() {
return spec;;
}
}
|
public class Guitar extends Instrument {
public Guitar(String serialNumber, double price, GuitarSpec spec) {
super(serialNumber, price, spec);
}}
public class Mandolin extends Instrument {
public Guitar(String serialNumber, double price, GuitarSpec spec) {
super(serialNumber, price, spec);
}
}
|
||악기 사양에 대한 추상 클래스||
|
public abstrct class InstrumentSpec {
//===============================================================================================
// 객체생성
//
---
private Builder builder;
private String medel;
private Type type;
private Wood backWood;
private Wood topWood;
//===============================================================================================
/**
- 악기에 대한 속성을 받는다.
- @throws Exception
*/
public InstrumentSpec(Builder builllder, String model, Type type, Wood backWood, Wood topWood) {
this.buillder = builllder;
this.medel = medel;
this.type = type;
this.backWood = backWood;
this.topWood = topWood;
}
/**
- builder, model, type 등을 위한 모든 메소드를 가져온다.
- @throws Exception
*/
public boolean matched(InstrumentSpec otherSpec) {
//===============================================================================================
// 모든 속성에 대해 다른 사양 객체와 비교한다.
//
---
if(builder != otherSpec.builder)
return false;
//
---
if((model != null) && (!model.equals("")) && (!model.equals(otherSpec.model)))
return false;
//
---
if(type != otherSpec.type);
return false;
//
---
if(backWood != otherSpec.backWood)
return false;
//
---
if(topWood != otherSpec.topWood)
return fllse;
//
---
return true;
//===============================================================================================
}
}
|
||Guitarspec.java||
|
public class GuitarSpec extends InstrumentSpec {
//===============================================================================================
// 기타에서만 필요한 속성 생성.
//
---
private int numStrings;
//===============================================================================================
//===============================================================================================
// SUPER 클래스 생성자 호출
//
---
public GuitarSpec(Builder builder, String model, Type type, int numStrings, Wood backWood, Wood topWood) {
//
---
super(builder, model, type, backWood, topWood);
//
---
this.numStrings = numStrings;
//
---
}
//===============================================================================================
public int getNumStrings() {
return numStrings;
}
/**
- 슈퍼 클래스 matches()를 오버라이드 한다.
- @throws Exception
*/
public boolean matches(InstrumentSpec otherSpec) {
//===============================================================================================
// 슈퍼 클래스 matches()를 사용해 공통된 속성, 클래스타입, 기타 특유의 속성을 비교한다.
//
---
if(!super.matched(otherSpec))
return false;
//
---
if(!(otherSpec instanceof GuitarSpec))
return flase;
//
---
GuitrSpec spec = (GuitarSpec) otherSpec;
//
---
if(numStrings != spec.numStrings)
return false;
//
---
return true;;
//===============================================================================================
}
}
|
||Mandolinspec.java||
|
import javax.swing.text.Style;
public class MandolinSpec extends InstrumentSpec {
//===============================================================================================
// 만돌린에만 필요한 속성 생성.
//
---
private Style style;
//===============================================================================================
//===============================================================================================
// SUPER 클래스 생성자 호출
//
---
public MandolinSpec(Builder builder, String model, Type type, int numStrings, Wood backWood, Wood topWood) {
//
---
super(builder, model, type, backWood, topWood);
//
---
this.style = style;
//
---
}
//===============================================================================================
public int getStyle() {
return style;
}
/**
- 슈퍼 클래스 matches()를 오버라이드 한다.
- @throws Exception
*/
public boolean matches(InstrumentSpec otherSpec) {
//===============================================================================================
// 슈퍼 클래스 matches()를 사용해 공통된 속성, 클래스타입, 기타 특유의 속성을 비교한다.
//
---
if(!super.matched(otherSpec))
return false;
//
---
if(!(otherSpec instanceof GuitarSpec))
return flase;
//
---
MandolinSpec spec = (MandolinSpec) otherSpec;
//
---
if(! style.equals(spec.style))
return false;
//
---
return true;;
//===============================================================================================
}
}
|
|
import java.util.Iterator;
import antlr.collections.List;
public class Inventory {
//
---
private List inventory;
//
---
public Inventory() {
inventory = new LinkedList();
}
public void addInstrument(String serialNumber, double price, InstrumentSpec spec) {
Instrument instrument = null;
//
---
if(spec instanceof GuitarSpec) {
instrument = new Guitar(serialNumber, price, (GutarSpec)spec);
}
//
---
else if(spec instanceof MandolinSpec) {
instrument = new Mandolin(serilNumber, price, (MandolinSpec) spec);
}
//
---
inventory.add(instrument);
//
---
}
public Instrument get(String serialNumber) {
for (Iterator i = inventory.iterator(); i.hasNext(); ){
Instrument instrument = (Instrument)i.next();
//
---
if(instrument.getSerialNumber().equals(serialNumber)) {
return instrument;
}
//
---
}
return null;
}
//===============================================================================================
// search(GuitarSpec)은 예전과 똑같이 동작한다.
//
---
public List search(MandolinSpec searchSpec) {
//
---
List matchingMandolins = new LinkedList();
//
---
for(Iterator i = inventory.iterator(); i.hasNext(); ) {
Mandolin mandolin = (Mandolin)i.next();
//
---
if(mandolin.getSpec().matches(searchSpec))
matchingMandolins.add(mandolin);
//
---
}
return matchingMandolins;
}
//===============================================================================================
}
}
h2. 위대한 소프트웨어로 향하는 +3단계+
Q. 릭의 검색도구가 *위대한* 소프트웨어입니까?
1. 새로운 검색 도구가 고객이 원하는 기능을 하나요?
{color:white}
+확실합니다. 프로그램이 기타와 만돌린을 찾아줍니다. 동시에 찾는 것은+
+아니지만, 그래서 해야 할 일은 대부분 하는 것 같습니다. 확실하게 하려면+
+릭에게 물어보는 게 나을 것 같습니다.+
{color}
2. 캡슐화, 중복 코드 피하기, 확장성이 좋게 만들기 같은 객체지향 원리를 사용하였나요?
{color:white}
+Instrumentspec을 사용할 때 캡슐화를 사용했고, Instrument와 Instrumentspec을+
+슈퍼 클래스로 만들 때 상속을 사용했습니다. 하지만 새로운 악기 타입을 추가하는 것은+
+여전히 많은 작업이 필요합니다...+
{color}
3. 릭의 프로그램은 재사용이 쉽나요? 프로그램의 한 부분을 고치면 다른 여러 부분들의
수정을 필요로 하나요? 프로그램이 느슨하게 결합되어 있나요?
{color:white}
+릭의 프로그램 일부만을 재사용하는 것이 좀 어렵습니다. 모든 것이 매우 단단히 연결되어 있고,+
+Instrumentspec이 실제로는 Instrument의 일부입니다. (집합(aggregation)에+
+대해 얘기했던 거 기억나요?)+
{color}
h3. 소프트웨어가 잘 설계 되었는지 알아보는 가장 좋은 방법중 하나는 사용해 보고 '수정'해 보는 것입니다.
<p 253 그림 참고>
-릭의 프로그램을 수정이 용이하고 확장성이 있는 위대한 소프트웨어로 만들려면 뭔가 할 일이 있습니다.
*객체지향 대참사* 에서 한번 알아보겠습니다.
h2. 문서에 대하여
* 이 문서는 [Head First Object-Oriented Analysis & Design|http://book.naver.com/bookdb/book_detail.php?bid=2920750]을 정리한 내용 입니다.
* 이 문서는 [오라클클럽|http://www.gurubee.net] [자바 웹개발자 스터디|제3차 자바 웹개발자 스터디] 모임에서 작성하였습니다.
* 이 문서를 다른 블로그나 홈페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^\^